import wx
from Constant import *
'''
GameObj_Master :
    
    Game object of player. User can control it through left, right, up and down key on keyboard.
    
    Player's favorite is diamond, it can eat diamond. In addition, player can push stone if there is
    
    a null space at pushing direction for stone. However, if player encounter the object that makes
    
    player bursting, the player will burst automatically.
'''
class GameObj_Master():
    '''
    Constructor : GameObj_Master
        mainMap - object pointer - mainMap
        mainFrame - object pointer of frame
    '''
    def __init__(self, mainMap, mainFrame):
        self._001_initialInstanceVariable(mainMap, mainFrame)
        self._002_bindAction()
    '''
    function _001 : initialize the variables used for this object
        mainMap - object pointer - mainMap
        mainFrame - object pointer of frame
    '''
    def _001_initialInstanceVariable(self, mainMap, mainFrame):
        #object pointer - MainMap
        self.mainMap = mainMap
        #object pointer - main frame
        self.mainFrame = mainFrame
        #record current position in map (row, column)
        self.posInMap = None
        #record whether master can walk now
        self.isAbleWalk = False
        #record whether pause walking
        self.isPauseWalk = False
        #timer of canceling the pause
        self.timer_cancelPause = wx.Timer()
    '''
    function _002 : bind object event to specific method
    '''
    def _002_bindAction(self):
        self.mainFrame.Bind(wx.EVT_KEY_DOWN, self.SLOT001_masterMove)
        self.timer_cancelPause.Bind(wx.EVT_TIMER, self.SLOT002_cancelPause)
    '''
    function _003 : judging whether the passing position is a obstacle for player
    '''
    def _003_judgePosCanWalk(self, pos_move):
        targetObjType = self.mainMap.GET001_objTypeIn_listCube(pos_move)
        return (not LIST_IS_OBSTACLE[str(GAME_OBJ_MASTER)][targetObjType])
    '''
    function _004 : judging whether the passing position is a diamond in map
    '''
    def _004_judgePosIsDiamond(self, pos):
        targetObjType = self.mainMap.GET001_objTypeIn_listCube(pos)
        if targetObjType == GAME_OBJ_DIAMOND :  #if next position is a diamond,posting event to object - MainMap
            wx.PostEvent(self.mainMap, NewEvt_eatDiamond(position = pos))
    '''
    function _005 : judging whether the player can push stone at direction - dirVector
    '''
    def _005_judgePushStone(self, dirVector):
        nextPos = (self.posInMap[0] + dirVector[0], self.posInMap[1] + dirVector[1])
        next2Pos = (nextPos[0] + dirVector[0], nextPos[1] + dirVector[1])
        #judge whether the next position of master is a stone
        isStone = self.mainMap.GET001_objTypeIn_listCube(nextPos) == GAME_OBJ_STONE
        #judge whether the next position of stone is a obstacle
        isSpace = (not self.mainMap.ACT004_judgePosIsOutOfRange(next2Pos)) and \
                  (not LIST_IS_OBSTACLE[str(GAME_OBJ_STONE)][self.mainMap.GET001_objTypeIn_listCube(next2Pos)])
        if isStone and isSpace:  #the master can push stone
            return True
        else :
            return False
    def ACT001_startPauseWalk(self, sec):
        self.isPauseWalk = True
        self.timer_cancelPause.Start(sec)
    '''
    function SET001 : set instance variable - posInMap
    '''
    def SET001_posInMap(self, pos):
        self.posInMap = pos
        self.mainMap.ACT014_setMapViewThroughMasterPos(self.posInMap)
    '''
    function SET002 : set instance variable - isAbleWalk
    '''
    def SET002_isAbleWalk(self, isAbleWalk):
        self.isAbleWalk = isAbleWalk
    '''
    function GET001 : get instance variable - posInMap
    '''
    def GET001_posInMap(self):
        return self.posInMap
    '''
    function SLOT001 : slot of moving the player
    '''
    def SLOT001_masterMove(self, event):
        if self.isAbleWalk and (not self.isPauseWalk):
            key = event.GetKeyCode()
            movRow = 0
            movCol = 0
            dir = None
            #check aspect of next moving
            if key == wx.WXK_UP :  #move up
                dir = ASP_UP
                movRow = -1
            elif key == wx.WXK_DOWN :  #move down
                dir = ASP_DOWN
                movRow = 1
            elif key == wx.WXK_LEFT :  #move left
                dir = ASP_LEFT
                movCol = -1
            elif key == wx.WXK_RIGHT :  #move right
                dir = ASP_RIGHT
                movCol = 1
            if dir != None :
                nextPosInMap = (self.posInMap[0] + movRow, self.posInMap[1] + movCol)
                #check whether the master can go to next position
                isNextPosLegal = (not self.mainMap.ACT004_judgePosIsOutOfRange(nextPosInMap)) and \
                                 (self._003_judgePosCanWalk(nextPosInMap))     
                if isNextPosLegal:  #go to next position if next position is legal
                    #judge whether master eats diamond
                    self._004_judgePosIsDiamond(nextPosInMap)
                    #master moves
                    self.mainMap.ACT002_MoveObj(self.posInMap, nextPosInMap, dir)
                    self.SET001_posInMap(nextPosInMap)
                elif movRow == 0 and self._005_judgePushStone((movRow, movCol)) :  #push stone
                    wx.PostEvent(self.mainMap.evtCollector, 
                                 NewEvt_pushStone(targetPos = nextPosInMap, dirVector = (movRow, movCol)))
                elif (self.mainMap.GET001_objTypeIn_listCube(nextPosInMap) == GAME_OBJ_EXIT) and \
                     (self.mainMap.GET002_isExitOpen()) :  #go to exit
                    self.mainMap.ACT003_changeObj(self.posInMap, GAME_OBJ_BLACK, 0)
                    wx.PostEvent(self.mainMap, NewEvt_gameEnd(EndType = END_GAME_GO_EXIT))
                else :  #master doesn't move,but changes the image according to the push aspect
                    self.mainMap.ACT003_changeObj(self.posInMap, GAME_OBJ_MASTER, dir)
                #pause walk temporarily
                self.ACT001_startPauseWalk(PLAYER_PAUSE_TIME)
                    
    def SLOT002_cancelPause(self, event):
        self.isPauseWalk = False
                